package com.kk.demo.unsface;

import java.lang.reflect.Field;
import java.util.Random;
import java.util.concurrent.Semaphore;

import sun.misc.Unsafe;

public class MyArray {

    /**
     * 共享的数组
    * @字段说明 data
    */
    private byte[] data;

    /**
     * 当前的索引下标
    * @字段说明 curPos
    */
    private int curPos;// 当前有效的数据位置，比如curPos=5，表示从0-5都是有值的，可以读取，追加写入的时候，也从这里开始

    /**
     * 操作对象
    * @字段说明 unsafeInstance
    */
    private Unsafe unsafeInstance = getUnsafe();

    /**
     * 操作许可变量
    * @字段说明 semap
    */
    private Semaphore semap = new Semaphore(1);

    /**
    * @字段说明 isUpd
    */
    private volatile boolean isUpd = false;

    public static Unsafe getUnsafe() {
        Field f;
        try {
            f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            Unsafe unsafe = (Unsafe) f.get(null);

            return unsafe;
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return null;

    }

    public MyArray(int size) {

        if (size <= 0) {
            size = 512;
        }

        data = new byte[size];
        curPos = 0;
    }

    public void writeByte(byte value) {
        try {
            // 获取许可
            semap.acquire();
            data[curPos] = value;
            curPos += 1;

            isUpd = true;
            // 强制刷新cache中的数据,使其他都可见
            unsafeInstance.storeFence();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 释放许可
            semap.release();
        }

    }

    public byte getbyte(int curr) {
        if (isUpd) {
            isUpd = false;
            // 使用读取栅栏，加载最新的数据
            unsafeInstance.loadFence();
        }

        if (curr <= curPos) {
            return data[curr];
        }
        return -1;
    }

    private static final Random rand = new Random();

    public static void main(String[] args) {

        final int size = 9999999;

        MyArray myarry = new MyArray(size);

        new Thread(() -> {
            for (int i = 0; i < size; i++) {
                myarry.writeByte((byte) ((i + 1000) % 127));
                // try {
                // Thread.currentThread().sleep(1l);
                // } catch (Exception e) {
                // // TODO Auto-generated catch block
                // e.printStackTrace();
                // }
            }
        }).start();

        System.out.println("当前大小:" + myarry.curPos);

        Thread[] thread = new Thread[10];

        for (int k = 0; k < 10; k++) {
            thread[k] = new Thread(() -> {
                for (int j = 0; j < size; j++) {
                    System.out.println("currPost:" + (myarry.curPos - 1) + "\t,值信息:" + myarry.getbyte(myarry.curPos - 1)
                            + "\tthreadId:" + Thread.currentThread().getId() + ",\ttime:" + System.nanoTime());
                    
                    try {
                        Thread.currentThread().sleep(2l);
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                
                }
            });
        }
        
        
        for (int i = 0; i < thread.length; i++) {
            thread[i].start();
        }
    }

}
